﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp1.userWin
{

    /// <summary>
    /// 包含枚举当前用户空间下所有窗口的方法。
    /// </summary>
    public static class WindowsHook
    {


        //获取当前窗口
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern IntPtr GetForegroundWindow();
        //窗口开关0    关闭窗口1    正常大小显示窗口2    最小化窗口3    最大化窗口
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
        //窗口开关0    关闭窗口1    正常大小显示窗口2    最小化窗口3    最大化窗口
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern int ShowWindowAsync(IntPtr hwnd, int nCmdShow);

        //设置此窗体为活动窗体
        [DllImport("user32", EntryPoint = "SetForegroundWindow")]
        internal static extern bool SetFocus(IntPtr hWnd);//设置此窗体为活动窗体
        //获取当前窗口位置
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        [StructLayout(LayoutKind.Sequential)]
        internal struct RECT
        {
            internal int Left;                             //最左坐标
            internal int Top;                             //最上坐标
            internal int Right;                           //最右坐标
            internal int Bottom;                        //最下坐标
        }

        [DllImport("user32", SetLastError = true)]
        internal static extern int GetWindowText(
            IntPtr hWnd,//窗口句柄 
            StringBuilder lpString,//标题 
            int nMaxCount //最大值 
         );

        /// <summary>
        ///   截图
        /// </summary>
        /// <param name="hdc">目标设备上下文的句柄</param>
        /// <param name="x">目标矩形左上角的x坐标（以逻辑单位表示</param>
        /// <param name="y">目标矩形左上角的y坐标</param>
        /// <param name="cx">源矩形和目标矩形的宽度</param>
        /// <param name="cy">源矩形和目标矩形的高度</param>
        /// <param name="hdcSrc">源设备上下文的句柄  </param>
        /// <param name="x1">源矩形左上角的x坐标</param>
        /// <param name="y1">源矩形左上角的y坐标</param>
        /// <param name="rop">栅格操作代码</param>
        /// <returns></returns>
        [DllImport("gdi32")]
        internal static extern bool BitBlt(
          IntPtr hdc,
          int x,
          int y,
          int cx,
          int cy,
          IntPtr hdcSrc,
          int x1,
          int y1,
           System.Int32 rop
         );

        /// <summary>
        /// 创建用于使用指定的名称的装置的Dc
        /// </summary>
        /// <param name="pwszDriver"></param>
        /// <param name="pwszDevice"></param>
        /// <param name="pszPort"></param>
        /// <param name="pdm"></param>
        /// <param name=""></param>
        /// <returns></returns>
        [DllImport("gdi32")]
        internal static extern IntPtr CreateDCA(
          string pwszDriver,
          string pwszDevice,
          string pszPort,
          IntPtr pdm
        );
        /// <summary>
        /// 根据窗口获取DC
        /// </summary>
        /// <param name="hWnd"></param>
        /// <returns></returns>
        [DllImport("user32")]
        internal static extern IntPtr GetDC(
            IntPtr hWnd // handle to window
        );

        //获取类的名字 
        [DllImport("user32.dll")]
        internal static extern int GetClassName(
            IntPtr hWnd,//句柄 
            StringBuilder lpString, //类名 
            int nMaxCount //最大值 
         );

        //根据坐标获取窗口句柄 
        [DllImport("user32")]
        internal static extern IntPtr WindowFromPoint(
         Point Point  //坐标 
        );

        //钩子子程必须按照HookProc(int nCode, Int32 wParam, IntPtr lParam)这种结构定义，三个参数会得到关于消息的数据。
        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam,int hHook);

        /// <summary>
        ///    安装钩子
        /// </summary>
        /// <param name="idHook"> 钩子类型，即确定钩子监听何种消息，上面的代码中设为2，即监听键盘消息并且是线程钩子，如果是全局钩子监听键盘消息应设为13，线程钩子监听鼠标消息设为7，全局钩子监听鼠标消息设为14。</param>
        /// <param name="lpfn">钩子子程的地址指针。如果dwThreadId参数为0 或是一个由别的进程创建的线程的标识，lpfn必须指向DLL中的钩子子程。 除此以外，lpfn可以指向当前进程的一段钩子子程代码。钩子函数的入口地址，当钩子钩到任何消息后便调用这个函数</param>
        /// <param name="hInstance">应用程序实例的句柄。标识包含lpfn所指的子程的DLL。如果threadId 标识当前进程创建的一个线程，而且子程代码位于当前进程，hInstance必须为NULL。可以很简单的设定其为本应用程序的实例句柄。</param>
        /// <param name="threadId">与安装的钩子子程相关联的线程的标识符。如果为0，钩子子程与所有的线程关联，即为全局钩子。</param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        internal static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        // 卸载钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        internal static extern bool UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        /// <summary>
        ///  继续下一个钩子
        /// </summary>
        /// <param name="idHook">变量记录返回的句柄，如果idHook不为0则说明钩子安装成功。</param>
        /// <param name="nCode">nCode参数是钩子代码，钩子子程使用这个参数来确定任务，这个参数的值依赖于Hook类型。</param>
        /// <param name="wParam">消息信息</param>
        /// <param name="lParam">消息信息</param>
        /// <returns></returns>
        internal static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
        /// <summary>
        /// 注入信息
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="wMsg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "SendMessageW")]
        internal static extern int SendMessage(IntPtr hwnd, IntPtr wMsg, IntPtr wParam, IntPtr lParam);


        /// <summary>
        /// 注入信息post
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="wMsg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "PostMessageW")]
        internal static extern int PostMessage(IntPtr hwnd, IntPtr wMsg, IntPtr wParam, IntPtr lParam);

        /// <summary>
        // 取得当前线程编号
        [DllImport("kernel32.dll")]
        static extern int GetCurrentThreadId();
        [StructLayout(LayoutKind.Sequential)]
        internal class KeyBoardHookStruct
        {
            internal int vkCode;
            internal int scanCode;
            internal int flags;
            internal int time;
            internal int dwExtraInfo;
        }

        /// <summary>
        /// 根据ip获取窗口句柄
        /// </summary>
        /// <param name="lpClassName"></param>
        /// <param name="lpWindowName"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto,EntryPoint = "FindWindow")]
        internal extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

        /// <summary>
        /// 将虚拟键代码转换（映射）为扫描代码或字符值
        /// </summary>
        /// <param name="uCode">虚拟密钥代码或扫描代码</param>
        /// <param name="uMapType">0.虚拟密钥代码，并转换为扫描代码虚拟密钥代码，并转换为扫描代码,1.扫描代码，并转换为虚拟键代码(2.3自己看文档,老子不想写了)</param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "MapVirtualKeyA")]
        internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
        

    }
}
